package basic;

import interfaces.CommandLine;

import java.util.Stack;
import java.util.Vector;

//@author A0098891H
public abstract class Manager implements CommandLine{
	public final static int ACTION_VIEW = 0;
	public final static int ACTION_ADD = 1;
	public final static int ACTION_DELETE = 2;
	public final static int ACTION_EDIT = 3;
	protected CRUDable _returnedObject;
	
	//keep track of the total amount of the transaction all the time
	protected double _totalAmountOfAll;
	
	protected Stack<String> _undoStack;//every manager has an undoStack
	protected Stack<String> _redoStack;//every manager has an undoStack
	protected int _nextId = 0; //
	/* remember to update it when initialize the manager, 
	 * keep on incrementing when adding new object
	 * implement nextFreeID mechanism for reuse of id is possible
	 * otherwise it will be exhausted by keep on creating and deleting objects.
	 */
	
	protected int _undoAction;
	protected int _action;
	protected int _savedId;
	protected int _savedPos;
	
	/**
	 * Save all the data in the manager, to be implemented by the child.
	 * @return true if all the data has been saved successfully, false otherwise.
	 * @Precondition none
	 * @Postcondition return true - data has been saved; false - data saving failed.
	 */
	public abstract boolean saveAll();
	/**
	 * loan all the data to the manager, to be implemented by the child.
	 * @return true if load successfully, false otherwise.
	 * @Precondition none
	 * @Postcondition return true - data has been loaded; false - data loading failed.
	 */
	public abstract boolean loadAll();

	/**
	 * Initialize the manager.
	 * @return true if initialized successfully; false if initialization failed.
	 * @Precondition none
	 * @Postcondition return true - initialization done; false - initialization failed.
	 */
	public boolean initialize()
	{
		_undoStack = new Stack<String>();
		_redoStack = new Stack<String>();
		_undoAction = 0;
		_action = 0;
		_savedId = -1;
		_savedPos = -1;
		_totalAmountOfAll = 0;
		return true;
	}
	
	/**
	 * Add CRUDable item into the Child Manager. To be implemented.
	 * @param item a CRUDable object
	 * @return the id of the item being added. -1 if the adding failed.
	 * @Precondition item != null
	 * @Postcondition return an integer >= 0 - added; < 0 adding failed.
	 */
	public abstract int add(CRUDable item);
	/**
	 * 
	 * @param item
	 * @param id
	 * @param pos
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public abstract boolean addTo(CRUDable item, int id, int pos);
	/**
	 * 
	 * @param id
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public abstract CRUDable get(int id);
	/**
	 * 
	 * @param id
	 * @param item
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public abstract CRUDable edit(int id, CRUDable item);
	/**
	 * 
	 * @param id
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public abstract CRUDable delete(int id);
	
	/**
	 * 
	 * @param list
	 * @param id
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public CRUDable getById(Vector<CRUDable> list, int id)
	{
		for(CRUDable it: list)
		{
			if(it._id==id)
				return it;
		}
		return null;
	}
	
	/**
	 * 
	 * @param mgr
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(Manager mgr)
	{
		_nextId = mgr._nextId;
		_totalAmountOfAll = mgr._totalAmountOfAll;
		_undoStack = new Stack<String>();//mgr._undoStack;
		_undoAction = mgr._undoAction;
		_redoStack = mgr._redoStack;
		_action = mgr._action;
		_savedId = mgr._savedId;
		_savedPos = mgr._savedPos;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public double getTotalAmountOfAll() {
		return _totalAmountOfAll;
	}
	public CRUDable get_returned() {
		return _returnedObject;
	}
}
